package cn.sdack.go.auth.service;

import cn.sdack.go.auth.dao.AccountDao;
import cn.sdack.go.auth.entity.AccountEntity;
import cn.sdack.go.auth.query.RegisterQuery;
import com.alibaba.fastjson2.JSONObject;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Random;

/**
 * @author sdack
 * @date 2023/12/24
 */
@Service
public class AccountServiceImpl implements AccountService{

    @Autowired
    AccountDao accountDao;

    @Autowired
    PasswordEncoder passwordEncoder;

    List<Integer> k = Arrays.asList(133, 149, 153, 173, 177, 180, 181, 189, 190, 191, 193, 199, 134, 135, 136, 137, 138, 139,
            147, 148, 150, 151, 152, 157, 157, 159, 172, 130, 131, 132, 145, 155, 156, 166, 167, 171, 175, 176, 185, 186, 196);

    Random random = new Random();

    @Transactional
    @Override
    public AccountEntity register(RegisterQuery param) throws IllegalAccessException {
        if (!param.getEmail().isEmpty()) {
            Optional<AccountEntity> optional = accountDao.findByEmailAndDelIsNull(param.getEmail());
            if (optional.isPresent()) {
                throw new IllegalAccessException("邮箱已存在");
            }
        }
        if (param.getMobile() > 100000) {
            Optional<AccountEntity> optional = accountDao.findByMobileAndDelIsNull(param.getMobile());
            if (optional.isPresent()) {
                throw new IllegalAccessException("手机号已存在");
            }
        }
        AccountEntity entity = new AccountEntity();
        String code = randomNumber();
        entity.setAccount(code);
        entity.setEmail(param.getEmail());
        entity.setPwd(passwordEncoder.encode(param.getPassword()));
        entity.setNickname(param.getNickname());
        entity.setIssActive(false); // 新注册未激活
        entity.setIssLock(false);
        return accountDao.save(entity);
    }

    /**
     * 根据电话号码创建简单账户并设置已激活
     * 需要认证 由资源服务器发起的注册
     * @param mobile
     * @return
     * @throws IllegalAccessException
     */
    @Transactional
    @Override
    public AccountEntity createSimpleAccount(Long mobile) throws IllegalAccessException {
        if (mobile > 100000) {
            Optional<AccountEntity> optional = accountDao.findByMobileAndDelIsNull(mobile);
            if (optional.isPresent()) {
                return optional.get();
            }
        }
        AccountEntity entity = new AccountEntity();
        String code = randomNumber();
        entity.setAccount(code);
        entity.setMobile(mobile);
        entity.setEmail("");
        entity.setPwd(null);
        entity.setNickname(code.toString());
        entity.setIssActive(true);
        entity.setIssLock(false);
        return accountDao.save(entity);
    }

    /**
     * 创建账户
     * @param param
     * @return
     * @throws IllegalAccessException
     */
    @Transactional
    @Override
    public AccountEntity createAccount(RegisterQuery param) throws IllegalAccessException {
        // 检查账户，合并账户
        AccountEntity accountEntity = mergeAccount(param);
        if (accountEntity != null) {
            return accountEntity;
        }
        AccountEntity entity = new AccountEntity();
        String code = randomNumber();
        entity.setAccount(code);
        entity.setMobile(param.getMobile());
        entity.setEmail(param.getEmail());
        if (StringUtils.hasLength(param.getPassword())) {
            entity.setPwd(passwordEncoder.encode(param.getPassword()));
        }
        entity.setNickname(param.getNickname());
        entity.setIssActive(true);
        entity.setIssLock(false);
        return accountDao.save(entity);
    }

    /**
     * 更新 用户信息
     * @param param
     * @return
     * @throws Exception
     */
    @Transactional
    @Override
    public JSONObject updateUserinfo(AccountEntity param) throws Exception {
        Optional<AccountEntity> optional = accountDao.findByAccount(param.getAccount());
        if (optional.isEmpty()) {
            throw new IllegalAccessException("用户不存在");
        }
        JSONObject jsonObject = new JSONObject();
        AccountEntity accountEntity = optional.get();
        if (param.getNickname() != null && !param.getNickname().isEmpty()) {
            accountEntity.setNickname(param.getNickname());
            jsonObject.put("nickname",param.getNickname());
        }
        if (param.getName() != null && !param.getName().isEmpty()) {
            accountEntity.setName(param.getName());
            jsonObject.put("name",param.getName());
        }
        if (param.getAvatar() != null && !param.getAvatar().isEmpty()) {
            accountEntity.setAvatar(param.getAvatar());
            jsonObject.put("avatar",param.getAvatar());
        }
        accountDao.save(accountEntity);

        return jsonObject;
    }

    /**
     * 设置锁定
     * @param account
     * @param status 0 不锁定，锁定
     * @throws Exception
     */
    @Transactional
    @Override
    public void setLock(String account, Integer status) throws Exception {
        boolean b = status == 0;
        Optional<AccountEntity> optional = accountDao.findByAccount(account);
        if (optional.isPresent()) {
            AccountEntity accountEntity = optional.get();
            accountEntity.setIssLock(!b);
            accountDao.save(accountEntity);
        } else {
            throw new IllegalAccessException("账户不存在");
        }
    }

    AccountEntity mergeAccount(RegisterQuery param) {
        if (param.getMobile() != null && param.getMobile() > 100000 && StringUtils.hasLength(param.getEmail())) {
            Optional<AccountEntity> optional = accountDao.findByMobileAndDelIsNull(param.getMobile());
            Optional<AccountEntity> optional1 = accountDao.findByEmailAndDelIsNull(param.getEmail());
            if (optional.isPresent() && optional1.isPresent()) {
                // 合并账户
                AccountEntity account1 = optional1.get();
                AccountEntity account = optional.get();
                AccountEntity result;
                if (account.getCreated() != null && account1.getCreated() != null) {
                    if (account.getCreated().isBefore(account1.getCreated())) {
                        result = account;
                        account1.setIssActive(false);
                        account1.setIssLock(true);
                        account1.setDel(LocalDateTime.now());
                        accountDao.save(account1);
                    } else {
                        result = account1;
                        account.setIssActive(false);
                        account.setIssLock(true);
                        account.setDel(LocalDateTime.now());
                        accountDao.save(account);
                    }
                    result.setMobile(param.getMobile());
                    result.setEmail(param.getEmail());
                    accountDao.save(result);
                    return result;
                }
                // 使用ID 判断
                if (account.getId() < account1.getId()) {
                    result = account;
                    account1.setIssActive(false);
                    account1.setIssLock(true);
                    account1.setDel(LocalDateTime.now());
                    accountDao.save(account1);
                } else {
                    result = account1;
                    account.setIssActive(false);
                    account.setIssLock(true);
                    account.setDel(LocalDateTime.now());
                    accountDao.save(account);
                }
                result.setMobile(param.getMobile());
                result.setEmail(param.getEmail());
                accountDao.save(result);
                return result;
            }
            if (optional.isPresent()) {
                return optional.get();
            }
            if (optional1.isPresent()) {
                return optional1.get();
            }
        }
        if (param.getMobile() != null && param.getMobile() > 100000) {
            Optional<AccountEntity> optional = accountDao.findByMobileAndDelIsNull(param.getMobile());
            if (optional.isPresent()) {
                return optional.get();
            }
        }
        if (StringUtils.hasLength(param.getEmail())) {
            Optional<AccountEntity> optional = accountDao.findByEmailAndDelIsNull(param.getEmail());
            if (optional.isPresent()) {
                return optional.get();
            }
        }
        return null;
    }


    String randomNumber() {
        int i = random.nextInt(k.size());
        Integer first = k.get(i);
        double random1 = Math.random();
        String last = String.valueOf(random1).substring(2, 11);
        String code = first + last;
        Optional<AccountEntity> optional = accountDao.findByAccount(code);
        if (optional.isPresent()) {
            return randomNumber();
        }
        return code;
    }
}
